﻿using Kimd.Logic;
using Kimd.Machine;
using Kimd.Motion;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using WorkStation.Common;

namespace WorkStation.Logic
{
    /// <summary>
    /// 下Tray模组
    /// </summary>
    public class UnloadTrayLogic : FlowBase
    {
        private UnloadTrayLogicStatus _status;
        //axis
        private Axis _unloadY;
        private Axis _liftEmpty;
        private Axis _liftFull;
        //cylinder
        private Cylinder _fullTrayGrab;
        private Cylinder _fullTrayHold;
        private Cylinder _emptyTrayGrab;
        private Cylinder _emptyTrayHold;
        //sensor
        private Sensor _fullTrayTooMany;
        private Sensor _hasFullTray;
        private Sensor _emptyTrayTooMany;
        private Sensor _hasEmptyTray;
        private Sensor _fullTrayLiftHasTray;
        private Sensor _emptyTrayLiftHasTray;
        private Sensor _ionizerAlarm;
        private Sensor _safetyBeamA;
        private Sensor _safetyBeamB;

        private Tray _trayStatus;
        public UnloadTrayLogic(string flowName, FlowManager flowmanager) 
            : base(flowName, flowmanager)
        {
            //axis
            _unloadY = MachineResource.Instance.MachineAxis["下料仓Y轴"];
            _liftEmpty = MachineResource.Instance.MachineAxis["下料仓空盘顶升"];
            _liftFull = MachineResource.Instance.MachineAxis["下料仓满盘顶升"];
            //cylinder
            _emptyTrayGrab = MachineResource.Instance.MachineCylinder["下料仓空盘移载定位"];
            _emptyTrayHold = MachineResource.Instance.MachineCylinder["下料仓空盘区夹持气缸"];
            _fullTrayGrab = MachineResource.Instance.MachineCylinder["下料仓满盘移载定位"];
            _fullTrayHold = MachineResource.Instance.MachineCylinder["下料仓满盘区夹持气缸"];
            //sensor
            _fullTrayTooMany = MachineResource.Instance.MachineSensor["下料仓空盘区满盘信号"];
            _hasFullTray = MachineResource.Instance.MachineSensor["下料仓空盘区有盘信号"];
            _emptyTrayTooMany = MachineResource.Instance.MachineSensor["下料仓满盘区满盘信号"];
            _hasEmptyTray = MachineResource.Instance.MachineSensor["下料仓满盘区有盘信号"];
            _fullTrayLiftHasTray = MachineResource.Instance.MachineSensor["下料仓空盘移载有盘"];
            _emptyTrayLiftHasTray = MachineResource.Instance.MachineSensor["下料仓满盘移载有盘"];

            _ionizerAlarm = MachineResource.Instance.MachineSensor["下料仓离子风扇报警"];
            _safetyBeamA = MachineResource.Instance.MachineSensor["下料仓安全光栅A"];
            _safetyBeamB = MachineResource.Instance.MachineSensor["下料仓安全光栅B"];
            //tray
            _trayStatus = new Tray(1, 2);
            _trayStatus.Helper.NewEmptyTray();
            //signal
            //GlobalVariable.OKTray.Helper.NewFullTray();
        }

        public override void Calibrate()
        {
            base.Calibrate();
        }

        public override void Home()
        {
            if (!CheckFlowCondition()) return;
            //clear warn and set servo on
            _liftFull.ClearAlarm();
            Thread.Sleep(200);
            _liftFull.SetServoOn();
            _liftEmpty.ClearAlarm();
            Thread.Sleep(200);
            _liftEmpty.SetServoOn();
            _unloadY.ClearAlarm();
            Thread.Sleep(200);
            _unloadY.SetServoOn();

            //z轴抬起后方可回零
            WaitForSignal("下料逻辑", "Z轴已抬起");
            if (!CheckFlowCondition()) return;

            //WaitSensorOff(_hasFullTray, "下料仓满盘区有盘,请取走!");
            if (!CheckFlowCondition()) return;
            //WaitSensorOff(_hasEmptyTray, "下料仓空盘区有盘,请取走!");
            if (!CheckFlowCondition()) return;

            if (!GlobalVariable.IsSystemAlreadyHome)
            {
                AxisGoHomeSimultaneously(new List<Axis>() { _liftEmpty, _liftFull });
                if (!CheckFlowCondition()) return;
                SingleAxisGoHome(_unloadY);
            }
            else
            {
                AxisMoveSimultaneously(new List<Axis>() { _liftEmpty, _liftFull }, new List<double>() { 0, 0 });
                if (!CheckFlowCondition()) return;
                SingleAxisMove2Point(_unloadY, 0);
                if (!CheckFlowCondition()) return;
            }

            AxisMoveSimultaneously(new List<Axis>() { _liftEmpty, _liftFull }, "移盘高度");
            if (!CheckFlowCondition()) return;
            MultiCylinderOperate(new List<Cylinder>() { _emptyTrayGrab, _fullTrayGrab }, 5000, new List<bool>() { false, false });
            if (!CheckFlowCondition()) return;

            _status = UnloadTrayLogicStatus.FirstTimeRun;
        }

        public override void Init(out string errInfo)
        {
            base.Init(out errInfo);
        }

        public override void InSingleRunMode()
        {
            base.InSingleRunMode();
        }

        public override void Method()
        {
            if (!CheckFlowCondition()) return;
            switch (_status)
            {
                case UnloadTrayLogicStatus.FirstTimeRun:
                    //到取盘位
                    SingleAxisMove2Point(_unloadY, "取盘位");
                    if (!CheckFlowCondition()) return;
                    //取一盘待测料
                    grabOneEmptyTray();
                    //满盘托盘有盘
                    _trayStatus.Helper.SetCellStatus(0, CellStatus.HasProduct);
                    //到下盘位
                    SingleAxisMove2Point(_unloadY, "下盘位");
                    if (!CheckFlowCondition()) return;

                    (FlowManager.Instance.SelectFlow("下料逻辑") as UnloadTesterLogic).NewOKTray();
                    //GlobalVariable.OKTray.Helper.NewEmptyTray();
                    WaitForSignal("下料逻辑", "料放完");
                    //到下盘位
                    SingleAxisMove2Point(_unloadY, "下盘位");
                    if (!CheckFlowCondition()) return;

                    SingleAxisMove2Point(_liftEmpty, "落盘高度");
                    if (!CheckFlowCondition()) return;
                    SingleCylinderOperate(_emptyTrayGrab, 5000, false);
                    if (!CheckFlowCondition()) return;

                    _status = UnloadTrayLogicStatus.GrabEmptyTrayForUnload;
                    break;

                case UnloadTrayLogicStatus.GrabEmptyTrayForUnload:
                    //到下盘位
                    SingleAxisMove2Point(_unloadY, "取盘位");
                    if (!CheckFlowCondition()) return;
                    //满盘托盘有盘，把他放下来
                    Task task1 = new Task(() =>
                    {
                        grabOneEmptyTray();
                    });
                    task1.Start();
                    //空盘托盘有料，把他回收
                    SingleAxisMove2Point(_liftFull, "取缓存高度");
                    if (!CheckFlowCondition()) return;
                    SingleCylinderOperate(_fullTrayGrab, 5000, true);
                    if (!CheckFlowCondition()) return;
                    _trayStatus.Helper.SetCellStatus(1, CellStatus.HasProduct);
                    //等待两个任务都完成
                    Task.WaitAll(task1);

                    _status = UnloadTrayLogicStatus.UnloadTray;

                    break;

                case UnloadTrayLogicStatus.UnloadTray:
                    //到下盘位
                    SingleAxisMove2Point(_unloadY, "下盘位");
                    if (!CheckFlowCondition()) return;
                    //空盘托盘有料，把他回收
                    
                    Task task2 = new Task(() =>
                    {
                        recycleOneFullTray();
                    });
                    task2.Start();

                    Task.WaitAll(task2);

                    (FlowManager.Instance.SelectFlow("下料逻辑") as UnloadTesterLogic).NewOKTray();
                    //GlobalVariable.OKTray.Helper.NewEmptyTray();
                    WaitForSignal("下料逻辑", "料放完");

                    SingleAxisMove2Point(_liftEmpty, "落盘高度");
                    if (!CheckFlowCondition()) return;
                    SingleCylinderOperate(_emptyTrayGrab, 5000, false);
                    if (!CheckFlowCondition()) return;

                    _status = UnloadTrayLogicStatus.GrabEmptyTrayForUnload;

                    break;
            }
        }

        public override void OnStop()
        {
            base.OnStop();
        }

        public override bool PreStartCheck()
        {
            return base.PreStartCheck();
        }

        public override void SpotCheck()
        {
            base.SpotCheck();
        }
        private void grabOneEmptyTray()
        {
            SingleAxisMove2Point(_liftEmpty, "顶盘高度");
            if (!CheckFlowCondition()) return;
            SingleCylinderOperate(_emptyTrayHold, 5000, true);
            if (!CheckFlowCondition()) return;
            SingleAxisMove2Point(_liftEmpty, "分盘高度");
            if (!CheckFlowCondition()) return;
            SingleCylinderOperate(_emptyTrayHold, 5000, false);
            if (!CheckFlowCondition()) return;
            SingleAxisMove2Point(_liftEmpty, "移盘高度");
            if (!CheckFlowCondition()) return;
            SingleCylinderOperate(_emptyTrayGrab, 5000, true);
            if (!CheckFlowCondition()) return;
        }
        private void recycleOneFullTray()
        {
            SingleAxisMove2Point(_liftFull, "顶盘低位");
            if (!CheckFlowCondition()) return;
            SingleCylinderOperate(_fullTrayHold, 5000, true);
            if (!CheckFlowCondition()) return;
            SingleAxisMove2Point(_liftFull, "顶盘高位");
            if (!CheckFlowCondition()) return;
            SingleCylinderOperate(_fullTrayHold, 5000, false);
            if (!CheckFlowCondition()) return;
            SingleCylinderOperate(_fullTrayGrab, 5000, false);
            if (!CheckFlowCondition()) return;
            SingleAxisMove2Point(_liftFull, "移盘高度");
            if (!CheckFlowCondition()) return;
        }
    }
    public enum UnloadTrayLogicStatus
    {
        [Description("第一次运行")]
        FirstTimeRun,
        [Description("放料并取空Tray")]
        GrabEmptyTrayForUnload,
        [Description("下Tray")]
        UnloadTray,
    }
}
